8.8
waitdemo1-1.c
/* waitdemo1-1.c - shows how parent pause until child finishes * creates two children and wait them quit. */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/wait.h> #define DELAY 2 int main() { int newpid, nnewpid; void child_code(int), parent_code(int,int); printf("before: mypid is %d\n", getpid()); if ((newpid = fork()) == -1) perror("fork"); else if (newpid == 0) child_code(DELAY); else{ if ((nnewpid = fork()) == -1) perror("fork"); else if (nnewpid == 0) child_code(DELAY); else parent_code(newpid, nnewpid); } return 0; } void child_code(int delay) { printf("child %d here. will sleep for %d seconds \n", getpid(), delay); sleep(delay); printf("child done. about to exit\n"); exit(17); } void parent_code(int childpid, int childpid2) { int wait_rv, i; for (i = 0; i < 2; i++){ wait_rv = wait(NULL); printf("done waiting for children, Wait returned: %d\n", wait_rv); } }
/* waitdemo1-1.c - shows how parent pause until child finishes * creates two children and wait them quit. */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #include <sys/wait.h> /* #define DELAY 2 */ int main(int argc, char **argv) { int newpid, num, i; void child_code(int), parent_code(int); srand((unsigned)time(NULL)); if (argc != 2){ fprintf(stderr, "Usage: %s NUM\n", *argv); return 1; }else{ num = atoi(argv[1]); } printf("before: mypid is %d\n", getpid()); for (i = 0; i < num; i++){ if ((newpid = fork()) == -1) perror("fork"); else if (newpid == 0){ child_code(rand() / 1000); break; }else{ rand(); // 主进程调用, 不然子进程永远处在第一次调用. } } if (newpid != -1 && newpid != 0) parent_code(num); return 0; } void child_code(int delay) { printf("child %d here. will sleep for %d micro seconds \n", getpid(), delay); usleep(delay); printf("child done. about to exit\n"); exit(17); } void parent_code(int num) { int wait_rv, i; for (i = 0; i < num; i++){ wait_rv = wait(NULL); printf("done waiting for children, Wait returned: %d\n", wait_rv); } }
8.9
/* waitdemo2.c - shows how parent gets child status */ #include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <stdlib.h> #define DELAY 5 int main() { int newpid; void child_code(int); void chld_handler(int); signal(SIGCHLD, chld_handler); printf("before: mypid is %d\n", getpid()); if ((newpid = fork()) == -1) perror("fork"); else if (newpid == 0) child_code(DELAY); else while(1){ printf("waiting...\n"); sleep(1); } return 0; } void child_code(int delay) { printf("child %d here. will sleep for %d seconds\n", getpid(), delay); sleep(delay); printf("child done. about to exit\n"); exit(17); } void chld_handler(int signum) { int wait_rv; int child_status; int high_8, low_7, bit_7; wait_rv = wait(&child_status); printf("done waiting for child. Wait returned: %d\n", wait_rv); high_8 = child_status >> 8; /* 1111 1111 0000 0000 */ low_7 = child_status & 0x7F; /* 0000 0000 0111 1111 */ bit_7 = child_status & 0x80; /* 0000 0000 0000 0000 */ printf("status: exit=%d, sig=%d, core=%d\n", high_8, low_7, bit_7); exit(0); }
8.11 + 8.12
/* prompting shell version 2 * Solves the 'one-shot' problem of version 1 * Uses execvp(), but fork()s first so that * the shell waits around to perform another * command * New problem: shell catches signals. Run vi, press ^C */ #include <stdio.h> #include <signal.h> #include <unistd.h> #include <sys/wait.h> #include <stdlib.h> #include <string.h> #define MAXARGS 20 #define ARGLEN 100 void execute(char **); int numargs; int main() { char *arglist[MAXARGS+1]; char argbuf[ARGLEN]; char *makestring(); void int_handler(int); signal(SIGINT, int_handler); numargs = 0; while(numargs < MAXARGS) { printf("Arg[%d]? ", numargs); if (fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n') arglist[numargs++] = makestring(argbuf); else { if (numargs > 0){ arglist[numargs] = NULL; execute(arglist); numargs = 0; } } } return 0; } void execute(char * arglist[]) { int pid, exitstatus; pid = fork(); switch(pid){ case -1: perror("fork failed"); exit(1); case 0: execvp(arglist[0], arglist); perror("execvp failed"); exit(1); default: while(wait(&exitstatus) != pid) ; printf("child exited with status %d, %d\n", exitstatus >> 8, exitstatus & 0x7F); } } char *makestring(char *buf) { char *cp; buf[strlen(buf) - 1] = '\0'; cp = malloc(strlen(buf) + 1); if (cp == NULL){ fprintf(stderr, "no memory\n"); exit(1); } strcpy(cp, buf); if (strcmp(cp, "exit") == 0) exit(0); return cp; } void int_handler(int signum) { numargs= 0; printf("\nArg[%d]? ", numargs); fflush(stdout); }